package cn.z2huo.productcenter.management.app.service.impl.risk;

import cn.z2huo.core.exception.ServerException;
import cn.z2huo.productcenter.enums.flag.AuditFlagEnum;
import cn.z2huo.productcenter.enums.flag.AvailableFlagEnum;
import cn.z2huo.productcenter.enums.flag.DeleteFlagEnum;
import cn.z2huo.productcenter.enums.flag.PublishFlagEnum;
import cn.z2huo.productcenter.management.app.code.CodeGenerateUtils;
import cn.z2huo.productcenter.management.app.service.api.risk.RiskService;
import cn.z2huo.productcenter.management.model.vo.risk.*;
import cn.z2huo.productcenter.mapper.risk.RiskMapper;
import cn.z2huo.productcenter.model.dataobject.risk.RiskDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 *
 * @author z2huo
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RiskServiceImpl implements RiskService {

    private final RiskMapper riskMapper;

    @Override
    public RiskVO get(GetRiskVO getRiskVO) {

        LambdaQueryWrapper<RiskDO> queryWrapper = Wrappers.lambdaQuery(RiskDO.class);
        queryWrapper.eq(RiskDO::getId, getRiskVO.getId())
                .eq(RiskDO::getRiskCode, getRiskVO.getRiskCode())
                .last("limit 1");
        RiskDO riskDO = riskMapper.selectOne(queryWrapper);
        if (riskDO == null || DeleteFlagEnum.DELETE.getValue().equals(riskDO.getDeleteFlag())) {
            throw new ServerException("产品不存在");
        }

        RiskVO riskVO = new RiskVO();
        BeanUtils.copyProperties(riskDO, riskVO);
        return riskVO;
    }

    @Transactional
    @Override
    public SaveUpdateResultVO save(SaveUpdateRiskVO saveUpdateRiskVO) {

        if (StringUtils.isNotBlank(saveUpdateRiskVO.getRiskCode()) || saveUpdateRiskVO.getId() != null) {
            throw new ServerException("已经存在产品，不能新增");
        }

        String newRiskCode = CodeGenerateUtils.RISK.generateMd5();

        RiskDO riskDO = new RiskDO()
                .setRiskName(saveUpdateRiskVO.getRiskName())
                .setRiskShortName(saveUpdateRiskVO.getRiskShortName())
                .setRiskEnName(saveUpdateRiskVO.getRiskEnName())
                .setRiskEnShortName(saveUpdateRiskVO.getRiskEnShortName())
                .setValidDate(saveUpdateRiskVO.getValidDate())
                .setInvalidDate(saveUpdateRiskVO.getInvalidDate())
                .setRiskCode(newRiskCode);

        riskDO.setAuditFlag(AuditFlagEnum.NEW.getValue())
                .setAvailableFlag(AvailableFlagEnum.UNAVAILABLE.getValue())
                .setPublishFlag(PublishFlagEnum.NOT_PUBLISH.getValue())
                .setDeleteFlag(DeleteFlagEnum.NOT_DELETE.getValue());

        int insertResult = riskMapper.insert(riskDO);
        if (insertResult <= 0) {
            throw new ServerException("新增产品失败");
        }
        return new SaveUpdateResultVO().setId(riskDO.getId()).setRiskCode(newRiskCode);
    }

    @Transactional
    @Override
    public SaveUpdateResultVO update(SaveUpdateRiskVO saveUpdateRiskVO) {

        if (StringUtils.isBlank(saveUpdateRiskVO.getRiskCode()) || saveUpdateRiskVO.getId() == null) {
            throw new ServerException("产品代码和 ID 未提供");
        }

        LambdaQueryWrapper<RiskDO> queryWrapper = Wrappers.lambdaQuery(RiskDO.class);
        queryWrapper.select(RiskDO::getAuditFlag, RiskDO::getDeleteFlag)
                .eq(RiskDO::getId, saveUpdateRiskVO.getId())
                .eq(RiskDO::getRiskCode, saveUpdateRiskVO.getRiskCode())
                .last("limit 1");
        RiskDO flagRiskDO = riskMapper.selectOne(queryWrapper);
        if (flagRiskDO == null || DeleteFlagEnum.DELETE.getValue().equals(flagRiskDO.getDeleteFlag())) {
            throw new ServerException("待更新产品不存在");
        }
        AuditFlagEnum oldAuditFlagEnum = AuditFlagEnum.fromValue(flagRiskDO.getAuditFlag());

        // todo 可能需要校验当前审核状态是否允许修改。

        RiskDO riskDO = new RiskDO().setId(saveUpdateRiskVO.getId());

        riskDO.setRiskName(saveUpdateRiskVO.getRiskName())
                .setRiskShortName(saveUpdateRiskVO.getRiskShortName())
                .setRiskEnName(saveUpdateRiskVO.getRiskEnName())
                .setRiskEnShortName(saveUpdateRiskVO.getRiskEnShortName())
                .setValidDate(saveUpdateRiskVO.getValidDate())
                .setInvalidDate(saveUpdateRiskVO.getInvalidDate());

        switch (oldAuditFlagEnum) {
            case NEW -> riskDO.setAuditFlag(AuditFlagEnum.NEW.getValue());
            case RETURN, RETURN_AFTER_MODIFY, MODIFY, PASS_AUDIT ->
                    riskDO.setAuditFlag(AuditFlagEnum.MODIFY.getValue());
        }
        int updateResult = riskMapper.updateById(riskDO);
        if (updateResult <= 0) {
            throw new ServerException("新增产品失败");
        }
        return new SaveUpdateResultVO().setId(saveUpdateRiskVO.getId()).setRiskCode(saveUpdateRiskVO.getRiskCode());
    }

    @Override
    public void delete(DeleteRiskVO deleteRiskVO) {

    }

    @Transactional
    @Override
    public void available(AvailableVO availableVO) {

        String riskCode = availableVO.getRiskCode();
        Long riskId = availableVO.getId();

        if (StringUtils.isBlank(riskCode) || riskId == null) {
            throw new ServerException("产品代码和 ID 未提供");
        }

        // 校验产品是否可以启用
        LambdaQueryWrapper<RiskDO> queryWrapper = Wrappers.lambdaQuery(RiskDO.class);
        queryWrapper.select(RiskDO::getAvailableFlag, RiskDO::getAuditFlag, RiskDO::getDeleteFlag)
                .eq(RiskDO::getId, riskId)
                .eq(RiskDO::getRiskCode, riskCode)
                .last("limit 1");
        RiskDO flagRiskDO = riskMapper.selectOne(queryWrapper);
        if (flagRiskDO == null || DeleteFlagEnum.DELETE.getValue().equals(flagRiskDO.getDeleteFlag())) {
            throw new ServerException("待启用产品不存在。产品代码为 " + riskCode);
        }
        AvailableFlagEnum availableFlagEnum = AvailableFlagEnum.fromValue(flagRiskDO.getAvailableFlag());
        if (AvailableFlagEnum.AVAILABLE == availableFlagEnum) {
            throw new ServerException("产品已启用。产品代码为 " + riskCode);
        }
        AuditFlagEnum auditFlagEnum = AuditFlagEnum.fromValue(flagRiskDO.getAuditFlag());
        if (AuditFlagEnum.PASS_AUDIT != auditFlagEnum) {
            throw new ServerException("产品未审核通过，不可启用。产品代码为 " + riskCode);
        }

        RiskDO updateRiskDO = new RiskDO().setId(riskId).setAvailableFlag(AvailableFlagEnum.AVAILABLE.getValue());
        int updateResult = riskMapper.updateById(updateRiskDO);
        if (updateResult <= 0) {
            throw new ServerException("启用产品失败.产品代码为 " + riskCode);
        }
    }

}
